﻿using System;
using System.Windows.Input;
using FFImageLoading.Forms;
using Xamarin.Forms;

namespace Moven.Controls
{
	public partial class CheckBox
	{
		static readonly Type SelfType = typeof(CheckBox);

		public static readonly BindableProperty ToggleCommandProperty = BindableProperty.Create(
			nameof(ToggleCommand), typeof(ICommand), SelfType, propertyChanged: OnToggleCommandChanged);

		public static readonly BindableProperty IsCheckedProperty = BindableProperty.Create(
			nameof(IsChecked), typeof(bool), SelfType, false, propertyChanged: OnIsCheckedChanged);

		public static readonly BindableProperty SizeProperty = BindableProperty.Create(
			nameof(Size), typeof(double), SelfType, 40.0,
			propertyChanged: OnSizeChanged);

		public static readonly BindableProperty CheckedImageProperty = BindableProperty.Create(
			nameof(CheckedImage), typeof(ImageSource), SelfType, 
			propertyChanged: OnCheckedImageChanged);

		public static readonly BindableProperty UncheckedImageProperty = BindableProperty.Create(
			nameof(UncheckedImage), typeof(ImageSource), SelfType,
			propertyChanged: OnUncheckedImageChanged);

		public static readonly BindableProperty EasingFunctionNameProperty = BindableProperty.Create(
			nameof(EasingFunctionName),
			typeof(string),
			SelfType,
			propertyChanged: OnEasingFunctionChanged, defaultValue: "SpringOut");

		public static readonly BindableProperty AnimationDurationProperty = BindableProperty.Create(
			nameof(AnimationDuration),
			typeof(int),
			SelfType,
			propertyChanged: OnAnimationDurationChanged, defaultValue: 200);

		public ICommand ToggleCommand
		{
			get { return (ICommand)GetValue(ToggleCommandProperty); }
			set { SetValue(ToggleCommandProperty, value); }
		}

		public bool IsChecked
		{
			get { return (bool)GetValue(IsCheckedProperty); }
			set { SetValue(IsCheckedProperty, value); }
		}

		public double Size
		{
			get { return (double)GetValue(SizeProperty); }
			set { SetValue(SizeProperty, value); }
		}

		public ImageSource CheckedImage
		{
			get { return (ImageSource)GetValue(CheckedImageProperty); }
			set { SetValue(CheckedImageProperty, value); }
		}

		public ImageSource UncheckedImage
		{
			get { return (ImageSource)GetValue(UncheckedImageProperty); }
			set { SetValue(UncheckedImageProperty, value); }
		}

		public string EasingFunctionName
		{
			get { return (string)GetValue(EasingFunctionNameProperty); }
			set { SetValue(EasingFunctionNameProperty, value); }
		}

		public int AnimationDuration
		{
			get { return (int)GetValue(AnimationDurationProperty); }
			set { SetValue(AnimationDurationProperty, value); }
		}

		public CachedImage ImageView => imageView;

		public CheckBox()
		{
			InitializeComponent();
			imageView.WidthRequest = imageView.HeightRequest = Size;
		}

		static void OnEasingFunctionChanged(BindableObject bindable, object oldValue, object newValue)
		{
			var checkBox = bindable as CheckBox;
			checkBox.animateSizeBehavior.EasingFunctionName = (string)newValue;
		}
			
		static void OnAnimationDurationChanged(BindableObject bindable, object oldValue, object newValue)
		{ 
			var checkBox = bindable as CheckBox;
			checkBox.animateSizeBehavior.Duration = (int)newValue;
		}

		static void OnCheckedImageChanged(BindableObject bindable, object oldValue, object newValue)
		{
			var checkBox = bindable as CheckBox;
			if (checkBox.IsChecked)
			{
				checkBox.imageView.Source = (ImageSource)newValue;
			}
		}

		static void OnUncheckedImageChanged(BindableObject bindable, object oldValue, object newValue)
		{
			var checkBox = bindable as CheckBox;
			if (!checkBox.IsChecked)
			{
				checkBox.imageView.Source = (ImageSource)newValue;
			}
		}

		static void OnSizeChanged(BindableObject bindable, object oldValue, object newValue)
		{
			var checkBox = bindable as CheckBox;
			var size = (double)newValue;
			checkBox.imageView.WidthRequest = checkBox.imageView.HeightRequest = size;
		}

		static void OnIsCheckedChanged(BindableObject bindable, object oldValue, object newValue)
		{
			Device.BeginInvokeOnMainThread(() =>
			{
				var checkBox = bindable as CheckBox;
				var @checked = (bool)newValue;
				checkBox.imageView.Source = @checked? checkBox.CheckedImage : checkBox.UncheckedImage;
			});
		}

		static void OnToggleCommandChanged(BindableObject bindable, object oldValue, object newValue)
		{
			var checkBox = bindable as CheckBox;
			var command = checkBox.ToggleCommand;
			checkBox.tapGestureRecognizer.Command = command;
		}
	}
}
